Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
puppeteer-core
Advanced tools
The puppeteer-core package is a version of Puppeteer, a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It is intended to be a lightweight version that can be used when you want to bring your own browser. It does not download any browsers by default, unlike the full puppeteer package.
Page Automation
Automate and control a web page, including navigation, screenshot taking, and DOM manipulation.
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({executablePath: '/path/to/your/Chrome'});
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
Form Submission
Automate form submissions by typing into fields and clicking buttons.
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({executablePath: '/path/to/your/Chrome'});
const page = await browser.newPage();
await page.goto('https://example.com/login');
await page.type('#username', 'myUsername');
await page.type('#password', 'myPassword');
await page.click('#submit');
await page.waitForNavigation();
await browser.close();
})();
Web Scraping
Extract data from web pages by running JavaScript in the context of the page.
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({executablePath: '/path/to/your/Chrome'});
const page = await browser.newPage();
await page.goto('https://example.com');
const data = await page.evaluate(() => {
return document.querySelector('h1').textContent;
});
console.log(data);
await browser.close();
})();
PDF Generation
Generate PDFs of web pages for offline viewing or archiving.
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({executablePath: '/path/to/your/Chrome'});
const page = await browser.newPage();
await page.goto('https://example.com', {waitUntil: 'networkidle0'});
await page.pdf({path: 'example.pdf', format: 'A4'});
await browser.close();
})();
Automated Testing
Perform automated testing on web applications, including end-to-end tests, performance testing, and more.
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({executablePath: '/path/to/your/Chrome', headless: false});
const page = await browser.newPage();
await page.goto('https://example.com');
// Perform various tests, like checking if a button exists
const buttonExists = await page.$('button') !== null;
console.assert(buttonExists, 'Button should exist on the page');
await browser.close();
})();
Playwright is a Node library to automate the Chromium, WebKit, and Firefox browsers with a single API. It is similar to puppeteer-core but provides support for multiple browsers out of the box. It also offers additional features like network interception and emulation capabilities.
Selenium WebDriver is one of the most well-known tools for automated web testing. It supports multiple browsers and languages, making it a versatile choice for web automation. Compared to puppeteer-core, Selenium is more mature and has a larger community but can be slower and more complex to set up.
Nightmare is a high-level browser automation library. It is built on top of Electron, which is a framework for creating native applications with web technologies. Nightmare is designed to be simpler and more approachable than Puppeteer, but it is less powerful and only works with Electron's version of Chromium.
Cypress is a front-end testing tool built for the modern web. It is both a library for writing automated tests and a test runner that can execute them. Cypress is more focused on testing than general browser automation and provides a rich interactive interface for developing tests.
Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.
Most things that you can do manually in the browser can be done using Puppeteer! Here are a few examples to get you started:
To use Puppeteer in your project, run:
npm i puppeteer
# or "yarn add puppeteer"
When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API (customizable through Environment Variables). For a version of Puppeteer purely for connection, see puppeteer-core
.
Puppeteer looks for certain environment variables to aid its operations. If Puppeteer doesn't find them in the environment during the installation step, a lowercased variant of these variables will be used from the npm config.
HTTP_PROXY
, HTTPS_PROXY
, NO_PROXY
- defines HTTP proxy settings that are used to download and run the browser.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD
- do not download bundled Chromium during installation step.PUPPETEER_TMP_DIR
- defines the directory to be used by Puppeteer for creating temporary files. Defaults to os.tmpdir()
.PUPPETEER_DOWNLOAD_HOST
- overwrite URL prefix that is used to download Chromium. Note: this includes protocol and might even include path prefix. Defaults to https://storage.googleapis.com
.PUPPETEER_DOWNLOAD_PATH
- overwrite the path for the downloads folder. Defaults to <root>/.local-chromium
, where <root>
is Puppeteer's package root.PUPPETEER_CHROMIUM_REVISION
- specify a certain version of Chromium you'd like Puppeteer to use. See puppeteer.launch
on how executable path is inferred.PUPPETEER_EXECUTABLE_PATH
- specify an executable path to be used in puppeteer.launch
.PUPPETEER_PRODUCT
- specify which browser you'd like Puppeteer to use. Must be one of chrome
or firefox
. This can also be used during installation to fetch the recommended browser binary. Setting product
programmatically in puppeteer.launch
supersedes this environment variable. The product is exposed in puppeteer.product
PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM
— specify Puppeteer download Chromium for Apple M1. On Apple M1 devices Puppeteer by default downloads the version for Intel's processor which runs via Rosetta. It works without any problems, however, with this option, you should get more efficient resource usage (CPU and RAM) that could lead to a faster execution time.:::danger
Puppeteer is only guaranteed to work with the bundled Chromium, use at your own risk.
:::
:::caution
PUPPETEER_*
env variables are not accounted for in puppeteer-core
.
:::
Every release since v1.7.0 we publish two packages:
puppeteer
is a product for browser automation. When installed, it downloads a version of
Chromium, which it then drives using puppeteer-core
. Being an end-user product, puppeteer
supports a bunch of convenient PUPPETEER_*
env variables to tweak its behavior.
puppeteer-core
is a library to help drive anything that supports DevTools protocol. puppeteer-core
doesn't download Chromium when installed. Being a library, puppeteer-core
is fully driven
through its programmatic interface and disregards all the PUPPETEER_*
env variables.
To sum up, the only differences between puppeteer-core
and puppeteer
are:
puppeteer-core
doesn't automatically download Chromium when installed.puppeteer-core
ignores all PUPPETEER_*
env variables.In most cases, you'll be fine using the puppeteer
package.
However, you should use puppeteer-core
if:
puppeteer-core
and write a custom install.js
script that downloads headless_shell
instead of Chromium to save disk space.puppeteer-core
is one of the ingredients and you want to postpone install.js
script execution until Chromium is about to be used.When using puppeteer-core
, remember to change the include line:
const puppeteer = require('puppeteer-core');
You will then need to call puppeteer.connect
or puppeteer.launch
with an explicit executablePath
or channel
option.
Puppeteer follows the latest maintenance LTS version of Node.
Puppeteer will be familiar to people using other browser testing frameworks. You create an instance
of Browser
, open pages, and then manipulate them with Puppeteer's API.
Example - navigating to https://example.com and saving a screenshot as example.png:
Save file as example.js
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
Execute script on the command line
node example.js
Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with Page.setViewport()
.
Example - create a PDF.
Save file as hn.js
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com', {
waitUntil: 'networkidle2',
});
await page.pdf({path: 'hn.pdf', format: 'a4'});
await browser.close();
})();
Execute script on the command line
node hn.js
See Page.pdf
for more information about creating pdfs.
Example - evaluate script in the context of the page
Save file as get-dimensions.js
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
// Get the "viewport" of the page, as reported by the page.
const dimensions = await page.evaluate(() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio,
};
});
console.log('Dimensions:', dimensions);
await browser.close();
})();
Execute script on the command line
node get-dimensions.js
See Page.evaluate
and related methods like Page.evaluateOnNewDocument
and Page.exposeFunction
.
Puppeteer offers a Docker image that includes Chromium along with the required dependencies and a pre-installed Puppeteer version. The image is available via the GitHub Container Registry. The latest image is tagged as latest
and other tags match Puppeteer versions. For example,
docker pull ghcr.io/puppeteer/puppeteer:latest # pulls the latest
docker pull ghcr.io/puppeteer/puppeteer:16.1.0 # pulls the image that contains Puppeteer v16.1.0
The image is meant for running the browser in the sandbox mode and therefore, running the image requires the SYS_ADMIN
capability. For example,
docker run -i --init --cap-add=SYS_ADMIN --rm ghcr.io/puppeteer/puppeteer:latest node -e "`cat docker/test/smoke-test.js`"
Replace the path to smoke-test.js
with a path to your script.
The script can import or require the puppeteer
module because it's pre-installed inside the image.
Currently, the image includes the LTS version of Node.js. If you need to build an image based on a different base image, you can use our Dockerfile
as the starting point.
Puppeteer can be used for testing Chrome Extensions.
:::caution
Extensions in Chrome / Chromium currently only work in non-headless mode and experimental Chrome headless mode.
:::
The following is code for getting a handle to the background page of an extension whose source is located in ./my-extension
:
const puppeteer = require('puppeteer');
(async () => {
const pathToExtension = require('path').join(__dirname, 'my-extension');
const browser = await puppeteer.launch({
headless: 'chrome',
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
],
});
const backgroundPageTarget = await browser.waitForTarget(
target => target.type() === 'background_page'
);
const backgroundPage = await backgroundPageTarget.page();
// Test the background page as you would any other page.
await browser.close();
})();
:::note
Chrome Manifest V3 extensions have a background ServiceWorker of type 'service_worker', instead of a page of type 'background_page'.
:::
:::note
It is not yet possible to test extension popups or content scripts.
:::
1. Uses Headless mode
Puppeteer launches Chromium in headless mode. To launch a full version of Chromium, set the headless
option when launching a browser:
const browser = await puppeteer.launch({headless: false}); // default is true
2. Runs a bundled version of Chromium
By default, Puppeteer downloads and uses a specific version of Chromium so its API
is guaranteed to work out of the box. To use Puppeteer with a different version of Chrome or Chromium,
pass in the executable's path when creating a Browser
instance:
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});
You can also use Puppeteer with Firefox Nightly (experimental support). See Puppeteer.launch
for more information.
See this article
for a description of the differences between Chromium and Chrome. This article
describes some differences for Linux users.
3. Creates a fresh user profile
Puppeteer creates its own browser user profile which it cleans up on every run.
Turn off headless mode - sometimes it's useful to see what the browser is
displaying. Instead of launching in headless mode, launch a full version of
the browser using headless: false
:
const browser = await puppeteer.launch({headless: false});
Slow it down - the slowMo
option slows down Puppeteer operations by the
specified amount of milliseconds. It's another way to help see what's going on.
const browser = await puppeteer.launch({
headless: false,
slowMo: 250, // slow down by 250ms
});
Capture console output - You can listen for the console
event.
This is also handy when debugging code in page.evaluate()
:
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
await page.evaluate(() => console.log(`url is ${location.href}`));
Use debugger in application code browser
There are two execution context: node.js that is running test code, and the browser
running application code being tested. This lets you debug code in the
application code browser; ie code inside evaluate()
.
Use {devtools: true}
when launching Puppeteer:
const browser = await puppeteer.launch({devtools: true});
Change default test timeout:
jest: jest.setTimeout(100000);
jasmine: jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
mocha: this.timeout(100000);
(don't forget to change test to use function and not '=>')
Add an evaluate statement with debugger
inside / add debugger
to an existing evaluate statement:
await page.evaluate(() => {
debugger;
});
The test will now stop executing in the above evaluate statement, and chromium will stop in debug mode.
Use debugger in node.js
This will let you debug test code. For example, you can step over await page.click()
in the node.js script and see the click happen in the application code browser.
Note that you won't be able to run await page.click()
in
DevTools console due to this Chromium bug. So if
you want to try something out, you have to add it to your test file.
Add debugger;
to your test, eg:
debugger;
await page.click('a[target=_blank]');
Set headless
to false
Run node --inspect-brk
, eg node --inspect-brk node_modules/.bin/jest tests
In Chrome open chrome://inspect/#devices
and click inspect
In the newly opened test browser, type F8
to resume test execution
Now your debugger
will be hit and you can debug in the test browser
Enable verbose logging - internal DevTools protocol traffic
will be logged via the debug
module under the puppeteer
namespace.
# Basic verbose logging
env DEBUG="puppeteer:*" node script.js
# Protocol traffic can be rather noisy. This example filters out all Network domain messages
env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'
Debug your Puppeteer (node) code easily, using ndb
npm install -g ndb
(or even better, use npx!)
add a debugger
to your Puppeteer (node) code
add ndb
(or npx ndb
) before your test command. For example:
ndb jest
or ndb mocha
(or npx ndb jest
/ npx ndb mocha
)
debug your test inside chromium like a boss!
Check out our contributing guide to get an overview of Puppeteer development.
FAQs
A high-level API to control headless Chrome over the DevTools Protocol
The npm package puppeteer-core receives a total of 6,808,559 weekly downloads. As such, puppeteer-core popularity was classified as popular.
We found that puppeteer-core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.